package com.abkj.platform.tail.service.impl;

import com.abkj.platform.base.dao.warp.MapperWrap;
import com.abkj.platform.base.dao.warp.SQLType;
import com.abkj.platform.tail.command.CommandFactory;
import com.abkj.platform.tail.cons.CommandType;
import com.abkj.platform.tail.service.DataService;
import com.abkj.platform.tail.service.SerialService;
import com.abkj.platform.util.PublicTool;
import com.abkj.platform.util.SerialPortUtil;
import gnu.io.CommPortIdentifier;
import gnu.io.PortInUseException;
import gnu.io.SerialPort;
import gnu.io.UnsupportedCommOperationException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service("serialService")
public class SerialServiceImpl implements SerialService {
	private SerialPort serialPort = null;

	@Autowired
	private MapperWrap mapperWrap;

	@Autowired
	private DataService dataService;

	public int resetSerial(String code) {
		if (StringUtils.isEmpty(code)) {
			code = "00000000";
		}
		this.serialPort = getSerialPort();
		if (this.serialPort == null)
			return 1;
		try {
			byte[] ret = writeAndRead(code, (byte) 1);
			if (ret != null) {
				code = PublicTool.getHexString(ret, 6, 8);
				System.out.println("编号为：" + code);
				return 0;
			}
			return 2;
		} catch (Exception e) {
		}
		return 3;
	}

	public String zeroOrRemove(String code, CommandType type) {
		this.serialPort = getSerialPort();
		if (this.serialPort == null) {
			return "打开串口失败";
		}
		if (type == CommandType.CLEAR)
			try {
				byte[] ret = writeAndRead(code, (byte) 33);
				if (ret != null) {
					return "0";
				}
				return "读取传感器返回数据超时";
			} catch (Exception e) {
				return "串口异常";
			}
		try {
			byte[] ret = writeAndRead(code, (byte) -128);
			if (ret != null) {
				return "0";
			}
			return "读取传感器返回数据超时";
		} catch (Exception e) {
		}
		return "串口异常";
	}

	private byte[] writeAndRead(String code, byte cmd) throws Exception {
		byte[] buffer = CommandFactory.getCommandBuff(code, cmd);
		PublicTool.printHexString(buffer);
		SerialPortUtil.write(this.serialPort, buffer);
		InputStream in = null;
		in = this.serialPort.getInputStream();
		byte[] ret = CommandFactory.getCommandReturn(in);
		if (this.serialPort != null) {
			try {
				this.serialPort.getOutputStream().close();
				this.serialPort.getInputStream().close();
			} catch (Exception localException) {
			}
			this.serialPort.close();
			this.serialPort = null;
		}
		return ret;
	}

	private SerialPort getSerialPort() {
		if (this.serialPort != null)
			return this.serialPort;
		List config = this.mapperWrap.findBySql("select * from config");
		Map con = (Map) config.get(0);
		String com = con.get("com").toString();
		int rate = Integer.parseInt(con.get("rate").toString());
		if (StringUtils.isEmpty(com))
			com = "COM1";
		try {
			Enumeration portList = CommPortIdentifier.getPortIdentifiers();
			while (portList.hasMoreElements()) {
				CommPortIdentifier portId = (CommPortIdentifier) portList.nextElement();
				if (portId.getPortType() == 1) {
					if (portId.getName().equals(com)) {
						this.serialPort = ((SerialPort) portId.open("Serial_Communication", 1000));
						this.serialPort.setSerialPortParams(rate, 8, 1, 0);
					} else {
						portId = null;
					}
				}
			}
		} catch (PortInUseException e) {
			this.serialPort = null;
			e.printStackTrace();
		} catch (UnsupportedCommOperationException e) {
			this.serialPort = null;
			e.printStackTrace();
		}
		return this.serialPort;
	}

	public String scan(String table) {
		String sql = "select id,code,info  ";
		if (table.equals("level")) {
			sql = sql + " ,type,num";
		}
		sql = sql + " from " + table;
		if ((table.equals("level")) || (table.equals("osmometer"))) {
			sql = sql + " where state=0";
		}
		List<Map> rets = this.mapperWrap.findBySql(sql);
		if (rets.size() == 0) {
			return "0";
		}
		this.serialPort = getSerialPort();
		if (this.serialPort == null)
			return "获取串口失败！！！";
		byte c;
		if (table.equals("rain"))
			c = 26;
		else
			c = 16;
		StringBuffer buff = new StringBuffer();

		for (Map r : rets)
			try {
				String code = r.get("code").toString();
				int old = NumberUtils.toInt(r.get("info").toString());
				int id = NumberUtils.toInt(r.get("id").toString());
				int leveltype = NumberUtils.toInt(String.valueOf(r.get("type")));
				int levelnum = NumberUtils.toInt(String.valueOf(r.get("num")));
				byte[] buffer = CommandFactory.getCommandBuff(code, c);
				PublicTool.printHexString(buffer);
				SerialPortUtil.write(this.serialPort, buffer);
				InputStream in = null;
				in = this.serialPort.getInputStream();
				byte[] ret = CommandFactory.getCommandReturn(in);
				int info = 0;
				if (ret != null) {
					if (CommandFactory.validate(ret)) {
						if (table.equals("rain"))
							this.dataService.rainData(ret);
						else
							this.dataService.operateWithScanData(ret, code, id, table, leveltype, levelnum);
					} else {
						info = 1;
						buff.append("传感器ID：" + id + ",返回数据校验错误！");
					}
				} else {
					info = -1;
					buff.append("传感器ID：" + id + ",返回数据超时！");
				}
				if (info != old)
					this.mapperWrap.excuteBySql(SQLType.UPDATE,
							"update " + table + " set info=" + info + " where id = " + id);
			} catch (Exception localException) {
			}
		if (this.serialPort != null) {
			try {
				this.serialPort.getOutputStream().close();
				this.serialPort.getInputStream().close();
			} catch (Exception localException1) {
			}
			this.serialPort.close();
			this.serialPort = null;
		}
		String ret = buff.toString();
		if (StringUtils.isEmpty(ret)) {
			return "0";
		}
		return ret;
	}

	public int setRainTime(String code) {
		this.serialPort = getSerialPort();
		if (this.serialPort == null)
			return 1;
		try {
			byte[] ret = writeAndRead(code, (byte) -112);
			PublicTool.printHexString(ret);
			return 0;
		} catch (Exception e) {
		}
		return 2;
	}

	public String getRainTime(String code) {
		this.serialPort = getSerialPort();
		if (this.serialPort == null)
			return "1";
		try {
			byte[] ret = writeAndRead(code, (byte) 48);
			return getDate(ret);
		} catch (Exception e) {
		}
		return "3";
	}

	private String getDate(byte[] recvBuf) {
		StringBuffer buff = new StringBuffer();
		buff.append(PublicTool.getHexString(recvBuf[14]));
		buff.append(PublicTool.getHexString(recvBuf[15]));
		buff.append(PublicTool.getHexString(recvBuf[16]));
		buff.append(PublicTool.getHexString(recvBuf[17]));
		buff.append(PublicTool.getHexString(recvBuf[18]));
		buff.append(PublicTool.getHexString(recvBuf[19]));
		String time = buff.toString();
		buff.setLength(0);
		return "20" + time;
	}
}